/*
 * Copyright 2008. Mount Sinai Hospital, Toronto, Canada.
 * 
 * Licensed under the Apache License, Version 2.0. You
 * can find a copy of the license at:
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * IN NO EVENT SHALL MOUNT SINAI HOSPITAL BE LIABLE TO ANY PARTY FOR DIRECT, 
 * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST 
 * PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, 
 * EVEN IF MOUNT SINAI HOSPITAL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 
 * DAMAGE.
 * 
 * MOUNT SINAI HOSPITAL SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND 
 * ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". 
 * MOUNT SINAI HOSPITAL HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, 
 * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 
 */

package com.sinai.mshab.visibility.rule;

import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

import com.sinai.mshab.visibility.VisibilityRule;

/**
 * Exercise the {@link ShowIfSelected} VisibilityRule.
 * 
 * @author Arthur Kalmenson
 */
public class ShowIfSelectedTst extends GWTTestCase {

	private VisibilityRule<ListBox, Widget, String> rule;

	/**
	 * Test to insure that constructing a {@link ShowIfSelectedTst} with null
	 * arguments throws an {@link IllegalArgumentException}.
	 */
	public void testNullConstArgs() {

		// test various permutations.
		nullConstArgument(null, null, null);
		nullConstArgument(new ListBox(), null, null);
		nullConstArgument(null, "blah", null);
		nullConstArgument(null, null, new TextBox());
		nullConstArgument(new ListBox(), null, new PasswordTextBox());
	}

	/**
	 * Insure that an {@link IllegalArgumentException} is thrown with the given
	 * null arguments.
	 * 
	 * @param parent
	 *            the parent widget.
	 * @param value
	 *            the value of the trigger for the parent widget.
	 * @param child
	 *            the child widget.
	 */
	private void nullConstArgument(ListBox parent, String value, Widget child) {

		try {
			rule = new ShowIfSelected(parent, value, child);
			fail("Should have failed");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that when the {@link ShowIfSelected} rule is created that
	 * the parent and child widgets remain visible.
	 */
	public void testVisibilityAtCreation() {

		ListBox list = new ListBox();
		list.addItem("item1");
		rule = new ShowIfSelected(list, "test", new TextBox());
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test to insure that when we have an empty {@link ListBox} and an empty
	 * trigger that the child widget is hidden.
	 */
	public void testEmptyListBoxEmptyTrigger() {

		rule = new ShowIfSelected(new ListBox(), "", new TextBox());

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());
	}

	/**
	 * Test to insure that when the {@link ListBox} is empty and the trigger is
	 * not empty that the child widget is not visible.
	 */
	public void testEmptyListBoxSingleTrigger() {

		rule = new ShowIfSelected(new ListBox(), "test", new TextBox());

		// execute the rule and make sure the child is invisible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());
	}

	/**
	 * Test a {@link ListBox} with one entry and a trigger that's not equal to
	 * that entry. We expect that the child will become invisible.
	 */
	public void testSingleItemListSingleTriggerChildNotVisible() {
		ListBox list = new ListBox();
		list.addItem("test");
		rule = new ShowIfSelected(list, "can't work", new PasswordTextBox());
		list.setSelectedIndex(0);

		// execute the rule and make sure the child is invisible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());
	}

	/**
	 * Test a {@link ListBox} with one item and a trigger set to that entry.
	 * When the item is selected, we expect the child widget to become visible.
	 */
	public void testSingleItemListSingleTriggerChildVisible() {
		ListBox list = new ListBox();
		list.addItem("test");
		rule = new ShowIfSelected(list, "test", new PasswordTextBox());
		list.setSelectedIndex(0);

		// make sure it's becoming visible.
		rule.getChildWidget().setVisible(false);

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test a {@link ListBox} with many items and a trigger set to one of the
	 * items. When one of the items is selected we expect the child widget to
	 * become visible. When another item is selected, we expect the child to
	 * become invisible.
	 */
	public void testMultiItemListSingleTriggerChildVisible() {
		ListBox list = new ListBox();
		list.addItem("test1");
		list.addItem("test2");
		list.addItem("test3");
		rule = new ShowIfSelected(list, "test2", new PasswordTextBox());
		list.setSelectedIndex(2);

		// execute the rule and make sure the child is invisible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());

		// select the trigger item.
		list.setSelectedIndex(1);
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test a {@link ListBox} with one item but multiple triggers, one of them
	 * having the item. We expect the child widget to become visible.
	 */
	public void testSingleItemListMultiTriggerChildVisible() {
		ListBox list = new ListBox();
		list.addItem("test");
		rule = new ShowIfSelected(list, "hi", new PasswordTextBox());
		rule.addTrigger("hello");
		list.setSelectedIndex(0);

		// execute the rule and make sure the child is invisible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());

		// add the trigger that matches the item.
		rule.addTrigger("test");
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test a {@link ListBox} that has multiple items and multiple triggers
	 * where some of the triggers match the items. We expect that when the
	 * correct item is selected, the child widget would appear.
	 */
	public void testMultiItemListMultiTriggerChildVisible() {
		ListBox list = new ListBox();
		list.addItem("test1");
		list.addItem("test2");
		list.addItem("test3");
		list.addItem("test4");
		rule = new ShowIfSelected(list, "test2", new PasswordTextBox());
		rule.addTrigger("test4");
		list.setSelectedIndex(1);

		// execute the rule and make sure the child is visible.
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());

		// select an item that's not a trigger item.
		list.setSelectedIndex(2);
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertFalse(rule.getChildWidget().isVisible());

		// select an item that is a trigger item.
		list.setSelectedIndex(3);
		rule.execute();
		assertTrue(rule.getParentWidget().isVisible());
		assertTrue(rule.getChildWidget().isVisible());
	}

	/**
	 * Test setting the parent widget null. We expect an
	 * {@link IllegalArgumentException} to be thrown.
	 */
	public void testSetNullParent() {
		rule = new ShowIfSelected(new ListBox(), "blah", new TextBox());
		try {
			rule.setParentWidget(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that setting a valid parent widget works.
	 */
	public void testValidParent() {
		rule = new ShowIfSelected(new ListBox(), "blah", new TextBox());
		ListBox parent = new ListBox();
		rule.setParentWidget(parent);
		assertEquals(parent, rule.getParentWidget());
	}

	/**
	 * Test to insure that setting a null child widget throws an
	 * {@link IllegalArgumentException}.
	 */
	public void testSetNullChild() {
		rule = new ShowIfSelected(new ListBox(), "blah", new TextBox());
		try {
			rule.setChildWidget(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	/**
	 * Test to insure that setting a valid child widget works.
	 */
	public void testValidChild() {
		rule = new ShowIfSelected(new ListBox(), "blah", new TextBox());
		PasswordTextBox checkBox = new PasswordTextBox();
		rule.setChildWidget(checkBox);
		assertEquals(checkBox, rule.getChildWidget());
	}

	/**
	 * Test to insure adding a null trigger results in an
	 * {@link IllegalArgumentException} being thrown.
	 */
	public void testAddNullTrigger() {
		rule = new ShowIfSelected(new ListBox(), "blah", new TextBox());
		try {
			rule.addTrigger(null);
			fail("Should have thrown IllegalArgumentException");
		} catch (IllegalArgumentException e) {
			assertTrue(true);
		}
	}

	@Override
	public String getModuleName() {
		return "com.sinai.mshab.MshabVisibility";
	}
}
